#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
// 之前内存开辟的方式
// int val = 20; // 在栈空间上开辟4个字节
// char arr[10] = {0}; //在栈空间上开辟10个字节的连续空间
// 1、空间开辟大小是固定的
// 2、数组在申明的时候，必须指定数组的长度，他所需要的内存，在编译时分配。

// malloc
// free 
// calloc
// realloc

// 有时候需要的空间大小在程序运行的时候才能知道，那就需要动态分配内存了

//  栈区  -  局部变量、函数的形参
//  堆区  -  动态分配的内存
//  静态区 - 全局变量、静态变量 

//  malloc 和free 都在stdlib.h头文件中 

// malloc :  向内存申请一块连续可用的空间，并返回指向这块空间的指针.    

// 重点：申请的内存不会进行初始化

// 如果开辟成功，返回一个指向开辟好空间的指针
// 重点：如果开辟失败，则返回一个NULL指针，因此malloc的返回值一定要做检查
// 返回值的类型是void *,所以malloc函数并不知道开辟空间的类型，具体在使用的时候使用者自己来决定
// 如果参数 size为0，malloc的行为的标准是未定义的，取决于编译器。

// c语言提供了另外一个函数free,专门用来做动态内存的释放和回收
// void free (void *ptr)
// 如果参数ptr指向的空间不是动态开辟的，那么free函数的行为是未定义的
// 如果参数ptr是NULL指针，那么函数什么事都不做。
int main()
{
    int *p = malloc(10 * sizeof(int)); // 此处不需要强转
    if(p == NULL){   // 如果申请失败,输出错误原因
        printf("%s \n", strerror(errno)); // 报错 Not enough space， 10 替换成 INT_MAX，使用INT_MAX 需要引入limits.h
    }else {
        for(int i=0;i<10;i++){
            p[i] = i;
        }

        for (int i = 0; i < 10; i++)
        {
            printf("%d ",p[i]);
        }

        printf("\n");
    }
    // 当动态申请的空间不再使用的时候，就应该还给操作系统
    free(p); // free之后 p仍保留着原来的地址
    p = NULL; // 所以此处将p置为NULL
    return 0;
}